package ru.susu.algebra.centralunits.alternating.tex.local;

import java.math.BigInteger;
import java.util.Collection;
import java.util.List;

import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;

import ru.susu.algebra.centralunits.CentralUnitsOptions;
import ru.susu.algebra.centralunits.alternating.MathMethodWithInitializers;
import ru.susu.algebra.centralunits.alternating.initializers.ExponentsInitializer;
import ru.susu.algebra.centralunits.alternating.initializers.LocalUnitsInitializer;
import ru.susu.algebra.centralunits.alternating.initializers.QuadraticFieldsInitializer;
import ru.susu.algebra.centralunits.alternating.initializers.SpecialRowsInitializer;
import ru.susu.algebra.chartable.constructor.AlternatingCharTableUtil;
import ru.susu.algebra.field.quadratic.QuadraticFieldGeneralForm;
import ru.susu.algebra.jtex.ITexElement;
import ru.susu.algebra.jtex.StringTexElement;
import ru.susu.algebra.jtex.TexBeginEndElement;
import ru.susu.algebra.jtex.formula.FormulaTexElement;
import ru.susu.algebra.jtex.formula.MathSymbols;
import ru.susu.algebra.jtex.utils.TexUtils;
import ru.susu.algebra.partition.Partition;
import ru.susu.algebra.properties.IPropertySource;
import ru.susu.algebra.util.CollectionUtils;
import ru.susu.algebra.util.NumberUtilities;

/**
 * @author akargapolov
 * @since: 13.09.2010
 */
public class LocalCaseMainTheorem extends MathMethodWithInitializers<ITexElement>
{
	private static final Class[] DEPENDENCIES = {SpecialRowsInitializer.class,  QuadraticFieldsInitializer.class, ExponentsInitializer.class, LocalUnitsInitializer.class};

/*	\begin{theorem}
	Пусть $\Un(Z(\Z A_{14}))$,
	тогда $\Un(Z(\Z A_{14}))$ имеет следующую подгруппу

	$\langle u_{20}(1+\omega_{13})^{43680}\rangle\times \langle u_{57}(19+8\omega_{33})^{27720}\rangle\times \langle u_{59}(\omega_{5})^{30240}\rangle$
	индекса, делящего

	$43680\cdot27720\cdot30240=2^{13}\cdot3^{6}\cdot5^{2}\cdot7^{3}\cdot11\cdot13$.
	Здесь $u_{20}$--локальная единица, соответствующая характеру группы $A_{14}$ степени $4752$,
	$u_{57}$--локальная единица, соответствующая характеру группы $A_{14}$ степени $29952$,
	$u_{59}$--локальная единица, соответствующая характеру группы $A_{14}$ степени $34320$,
	$\omega_{13}=\frac{1+\sqrt{13}}{2}$,
	$\omega_{33}=\frac{1+\sqrt{33}}{2}$,
	$\omega_{5}=\frac{1+\sqrt{5}}{2}$.
	\end{theorem}*/
	@Override
	protected ITexElement directRun(final IPropertySource ps) throws Exception
	{
		TexBeginEndElement theorem = TexBeginEndElement.threorem();

		String group = "\\Un(Z(\\Z A" + TexUtils.index(CentralUnitsOptions.getNumber(ps)) + "))";
		List<Partition> specialRows = SpecialRowsInitializer.listSpecialNotIntegerCharacterRows(ps);
		StringBuffer buffer = new StringBuffer();
		if (specialRows.size() == 1)
		{
			buffer.append("$" + group + " = " + getOneUnit(ps, specialRows.iterator().next()) + "$.\n");
		}
		else
		{
			Collection<BigInteger> pows = LocalUnitsInitializer.getPows(ps).values();
			buffer.append("Пусть $" + group + "$,\n тогда $" + group + "$ имеет следующую подгруппу\n$").append(
					CollectionUtils.toString(Collections2.transform(specialRows, new Function<Partition, String>()
					{
						@Override
						public String apply(Partition partition)
						{
							return getOneUnit(ps, partition);
						}
					}), FormulaTexElement.TIMES)).append("$\n индекса, делящего \n\n$" +
							CollectionUtils.toString(pows, MathSymbols.CDOT) + "=" +
							TexUtils.getFactorization(NumberUtilities.product(pows)) + "$.\n");
		}

		buffer.append("Здесь ");
		List<String> omegas = Lists.newArrayList();
		for (Partition partition : SpecialRowsInitializer.listSpecialNotIntegerCharacterRows(ps))
		{
			buffer.append("$u" + TexUtils.index(SpecialRowsInitializer.getRowNumber(ps, partition)) + "$--локальная единица, ")
				.append("соответствующая характеру группы $A" + TexUtils.index(partition.getPresentedNumber()) + "$")
				.append(" степени $" + AlternatingCharTableUtil.calcAlternatingDegree(partition) + "$,\n");
			QuadraticFieldGeneralForm omega = QuadraticFieldsInitializer.getOmega(ps, partition);
			omegas.add("$" + TexUtils.toTexString(omega) + " = " + FormulaTexElement.frac("1 + " + FormulaTexElement.sqrt(omega.getD()), "2") + "$");
		}
		buffer.append(CollectionUtils.toString(omegas, ",\n")).append(".");

		theorem.addSubElement(StringTexElement.text(buffer.toString()));
		return theorem;
	}

	private String getOneUnit(IPropertySource ps, Partition partition)
	{
		return FormulaTexElement.LANGLE + " u" + TexUtils.index(SpecialRowsInitializer.getRowNumber(ps, partition)) +
			TexUtils.inBrackets(TexUtils.toTexString(QuadraticFieldsInitializer.getGeneralUnit(ps, partition))) + TexUtils.pow(LocalUnitsInitializer.getPow(ps, partition)) +
			FormulaTexElement.RANGLE;
	}

	@Override
	protected Class[] getDependentInitializers()
	{
		return DEPENDENCIES;
	}

}
